#pragma region LICENSE
// 
// *LICENSE:
// Copyright (c) 2013 - 2014, "cheat_code" <cheat_code@aim.com>.
// Use the code is allowed under the Artistic License 2.0 terms,
// as specified in the LICENSE file distributed with this code,
// or available from: http://opensource.org/licenses/artistic-license-2.0
//
#pragma endregion LICENSE

#include "Cheat_Code.h"

void Cheat_Code::Cheat::FlagHandler( void )
{
	if( Flags &( CheatFlags::EnableBytes_NOP ) )
	{
		this->EnableBytes = new char[ this->EnableBytesLength + 1 ];
		::memset( this->EnableBytes, 0x90, sizeof( char ) * this->EnableBytesLength );
		this->EnableBytes[ this->EnableBytesLength ] = '\0';
	}

	if( this->Flags &( CheatFlags::DisableBytes_NOP ) )
	{
		this->DisableBytes = new char[ this->DisableBytesLength + 1 ];
		::memset( this->DisableBytes, 0x90, sizeof( char ) * this->DisableBytesLength );
		this->DisableBytes[ this->DisableBytesLength ] = '\0';
	}
	else if( this->Flags &( CheatFlags::DisableBytes_Original ) )
	{
		this->DisableBytes = new char[ DisableBytesLength + 1 ];
		::memcpy( ( void * )this->DisableBytes,
				  ( const void* )this->Address,
				  ( sizeof( char ) * this->DisableBytesLength ) );
		this->DisableBytes[ this->DisableBytesLength ] = '\0';
	}
	else if( this->Flags &( CheatFlags::DisableBytes_OriginalEx ) )
	{
		this->DisableBytes = new char[ this->EnableBytesLength + 1 ];
		::memcpy( ( void * )this->DisableBytes,
				  ( const void* )this->Address,
				  ( sizeof( char ) * this->EnableBytesLength ) );
		this->DisableBytes[ this->EnableBytesLength ] = '\0';
		this->DisableBytesLength = this->EnableBytesLength;
	}
};

int Cheat_Code::Cheat::Enable( __in bool p_Enable )
{
	if( p_Enable != this->Enabled )
	{
		if( p_Enable && this->EnableBytes > 0 && this->EnableBytesLength != 0 )
			Util::WriteMemory( this->Address, this->EnableBytes, this->EnableBytesLength );
		else if( !p_Enable && this->DisableBytes > 0 && this->DisableBytesLength != 0 )
			Util::WriteMemory( this->Address, this->DisableBytes, this->DisableBytesLength );
		else return( 0 );

		this->Enabled = p_Enable;
	}
	return( 1 );
};

void Cheat_Code::Util::WriteMemory( __in unsigned long Address,
									__in char* Bytes,
									__in unsigned int Length )
{
	unsigned long OriginalProtection = 0;

	::VirtualProtect( ( void* )( Address ), Length, PAGE_EXECUTE_READWRITE, &OriginalProtection );
	::memcpy( ( void * )Address, Bytes, Length );
	::VirtualProtect( ( void* )( Address ), Length, OriginalProtection, &OriginalProtection );
};

void Cheat_Code::Util::WriteNOP( __in unsigned long Address, __in unsigned int Length )
{
	char NOPs[ 50 ];
	::memset( NOPs, 0x90, Length );
	Cheat_Code::Util::WriteMemory( Address, NOPs, Length );
};